package utils;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;
import ArithmeticObjects.*;
import crypto.*;

/**
 * This class defines and implements ProtInfo object, which will contain all data
 * extracted from protInfo.xml file. It holds values as ByteTrees for later use.
 * @author yuvalshu
 *
 */
public class ProtInfo {
	// private members
	private byte[] f;
	private int numParties;
	private int threshold;
	private int maxCiphers;
	private int numRandomBits;
	private int statError;
	private int numChallengeBits;	
	private HashFunction ROHash;
	private PRG prg;
	private ModularGroup group;


	/**
	 * Constructor, Retrieves and stores all public parameters from an XML protocol info file.
	 * @param fileName
	 * @throws Exception 
	 */
	public ProtInfo(String fileName) throws Exception{

		
		File fXmlFile = new File(fileName);
		this.f = ByteArrUtils.ByteArrayFromFile(fXmlFile);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(fXmlFile);
		Element procInfoElem = doc.getDocumentElement();
		// extract num of parties
		String value = getTagValue("nopart", procInfoElem);
		this.numParties = Integer.parseInt(value);

		// extract threshold
		value = getTagValue("thres", procInfoElem);
		this.threshold = Integer.parseInt(value);

		// extract modgroup
		value = getTagValue("pgroup", procInfoElem);
		// re-arrange string
		int index = value.indexOf("::");
		value = value.substring(index+2);
		value = value.replaceAll("\n", "");
		// umrashal mod group
		ByteTree modGroupTree = new ByteTree(value);
		this.group = MarshalServices.unmarshalModGroup(modGroupTree);

		// extract max Ciphertexts
		value = getTagValue("maxciph", procInfoElem);
		this.maxCiphers = Integer.parseInt(value);

		// extract statistical error
		value = getTagValue("statdist", procInfoElem);
		this.statError = Integer.parseInt(value);

		// extract random bits and challanges length
		value = getTagValue("cbitlenro", procInfoElem);
		this.numChallengeBits = Integer.parseInt(value);
		value = getTagValue("vbitlenro", procInfoElem);
		this.numRandomBits = Integer.parseInt(value);

		// extract PRG hashfunction and create PRG
		value = getTagValue("prg", procInfoElem);
		this.prg = new PRG(new HashFunction(value));

		// extract RO hashfunction
		value = getTagValue("rohash", procInfoElem);
		this.ROHash = new HashFunction(value);
}

/**
 * Extracts value for tag in given XML element.
 * @param sTag
 * @param eElement
 * @return string with value
 */
private static String getTagValue(String sTag, Element eElement) {
	NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
	Node nValue = (Node) nlList.item(0);

	return nValue.getNodeValue();
}


/**
 * Returns the number of parties participating in the mix-net (aka k).
 */
public int getNumParties(){
	return numParties;
}

/**
 * Returns the maximum number if mix-servers that must be corrupted to break the privacy of the senders.
 */

public int getThreshold() {
	return threshold;
}
/**
 * Returns the number of max ciphers
 */
public int getMaxCiphers() {
	return maxCiphers;
}
/**
 * Returns the number of random bits in each vector used for batching in proofs.   
 */
public int getNumRandomBits() {
	return numRandomBits;
}
/**
 * returns the acceptable statistical error when sampling random
 * values. 
 */
public int getStatError() {
	return statError;
}
/**
 * Returns the number of bits used in the challenge of the verifier
 * in zero-knowledge proofs
 */
public int getNumChallengeBits() {
	return numChallengeBits;
}
/**
 * Returns the HashFunction to be used in the RandomOracle instances.
 * @return
 */
public HashFunction getROHash() {
	return ROHash;
}
/**
 * Returns a PRG instance created with the hash function described in the file.
 * @return
 */
public PRG getPrg() {
	return prg;
}

/**
 * Returns the underlying modular group used in the proofs.
 */
public ModularGroup getGroup() {
	return group;
}
/**
 * Returns a byte array containing the entire xml file.
 * @return
 */
public byte[] getF(){
	return f;
}

}
